/**
 * 
 */
package se.cirrus.base.com;

import java.io.*;
import java.net.*;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.logging.LogManager;
import java.util.logging.Logger;

import se.cirrus.base.error.CommunicationException;
import se.cirrus.base.error.InvalidStateException;

/**
 * @author Winquman
 *
 */
public class BasicIPCommunicator implements Communicator {

	public static int STATIC_PORT = 9500;
	
	private String hostname;
	private int port;
	private CommunicationState state;
	private Logger log;
	
	private Socket s;
	private BufferedReader in;
	private BufferedWriter out;
	
	/**
	 * 
	 */
	public BasicIPCommunicator(String hostname) {
		state = new CommunicationState();
		this.hostname = hostname;
		port = STATIC_PORT;
		
		log = LogManager.getLogManager().getLogger("ALL");
		
		log.fine("A communicator has been initialized by hostname.");
	}
	
	public BasicIPCommunicator(Socket s) {
		state = new CommunicationState();
		hostname = s.getInetAddress().getHostAddress();
		port = s.getPort();
		this.s = s;
		
		log.fine("A communicator has been initialized by socket.");
	}

	/* (non-Javadoc)
	 * @see se.cirrus.base.com.Communicator#send(se.cirrus.base.com.Message)
	 */
	@Override
	public void send(Message message) throws CommunicationException,
			InvalidStateException {
		
		log.fine("Sending message through communicator: " + message);

		try {
			out.write(message.toString());
			log.fine("Sent a message to " + this + ": " + message);
		} catch (IOException e) {
			
			e.printStackTrace();
			throw new CommunicationException("Error when sending data!", e);
		}

	}

	/* (non-Javadoc)
	 * @see se.cirrus.base.com.Communicator#getState()
	 */
	@Override
	public CommunicationState getState() {
		// TODO Auto-generated method stub
		return null;
	}
	
	public void connect() throws CommunicationException, InvalidStateException {
		
		log.fine("Attempting to connect to " + hostname + ":" + port);
		try{
			s = new Socket(hostname, port);
			log.fine("Socket initialized!");
			out = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
			in = new BufferedReader(new InputStreamReader(s.getInputStream()));
			
			log.info("Connected to host: " + hostname);
		} catch(IOException e) {
			log.severe("Error while trying to connect to " + hostname + ":" + port);
			throw new CommunicationException("A read or write error occured when trying to connect to: " +
					hostname + " on port " + port, e);
		} 
	}
	
	public void disconnect() throws CommunicationException, InvalidStateException {
		
	}

	@Override
	public void setIncomingQueue(ConcurrentLinkedQueue<Message> mq)
			throws InvalidStateException {
		// TODO Auto-generated method stub
		
	}

	@Override
	public Message getNext() throws CommunicationException,
			InvalidStateException {
		
		try {
			if(in.ready()) {
				log.fine("There is a new message from peer: " + this);
				return new BasicIPMessage(in.readLine());
			}
			else
				return null;
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			throw new CommunicationException("Error while recieving message from peer.", e);
		}
	}

	
	public String toString () {
		return "<-" + hostname + "->";
	}

}
